#include "sdk.h"

namespace { static const bool s_case_sensitive = true; }

CompileOptionsBase::CompileOptionsBase()
  : m_Modified( false ),
    m_AlwaysRunPostCmds( false ) {
}

CompileOptionsBase::~CompileOptionsBase() {
}

void CompileOptionsBase::SetLinkerOptions( const wxArrayString& linkerOpts ) {
  if( m_LinkerOptions == linkerOpts ) {
    return;
  }
  m_LinkerOptions = linkerOpts;
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetLinkerOptions() const {
  return m_LinkerOptions;
}

void CompileOptionsBase::SetCompilerOptions( const wxArrayString& compilerOpts ) {
  if( m_CompilerOptions == compilerOpts ) {
    return;
  }
  m_CompilerOptions = compilerOpts;
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetCompilerOptions() const {
  return m_CompilerOptions;
}

void CompileOptionsBase::SetResourceCompilerOptions( const wxArrayString& resourceCompilerOpts ) {
  if( m_ResourceCompilerOptions == resourceCompilerOpts ) {
    return;
  }
  m_ResourceCompilerOptions = resourceCompilerOpts;
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetResourceCompilerOptions() const {
  return m_ResourceCompilerOptions;
}

void CompileOptionsBase::SetIncludeDirs( const wxArrayString& includeDirs ) {
  if( m_IncludeDirs == includeDirs ) {
    return;
  }
  m_IncludeDirs.Clear();
  for( size_t i = 0; i < includeDirs.GetCount(); ++i ) {
    wxString entry = UnixFilename( includeDirs[i] );
    if( m_IncludeDirs.Index( entry, s_case_sensitive ) == wxNOT_FOUND ) {
      m_IncludeDirs.Add( entry );
    }
  }
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetIncludeDirs() const {
  return m_IncludeDirs;
}

void CompileOptionsBase::SetResourceIncludeDirs( const wxArrayString& resIncludeDirs ) {
  if( m_ResIncludeDirs == resIncludeDirs ) {
    return;
  }
  m_ResIncludeDirs.Clear();
  for( size_t i = 0; i < resIncludeDirs.GetCount(); ++i ) {
    wxString entry = UnixFilename( resIncludeDirs[i] );
    if( m_ResIncludeDirs.Index( entry, s_case_sensitive ) == wxNOT_FOUND ) {
      m_ResIncludeDirs.Add( entry );
    }
  }
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetResourceIncludeDirs() const {
  return m_ResIncludeDirs;
}

void CompileOptionsBase::SetLibDirs( const wxArrayString& libDirs ) {
  if( m_LibDirs == libDirs ) {
    return;
  }
  m_LibDirs.Clear();
  for( size_t i = 0; i < libDirs.GetCount(); ++i ) {
    wxString entry = UnixFilename( libDirs[i] );
    if( m_LibDirs.Index( entry, s_case_sensitive ) == wxNOT_FOUND ) {
      m_LibDirs.Add( entry );
    }
  }
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetLibDirs() const {
  return m_LibDirs;
}

void CompileOptionsBase::SetBuildScripts( const wxArrayString& scripts ) {
  if( m_Scripts == scripts ) {
    return;
  }
  m_Scripts.Clear();
  for( size_t i = 0; i < scripts.GetCount(); ++i ) {
    wxString entry = UnixFilename( scripts[i] );
    if( m_Scripts.Index( entry, s_case_sensitive ) == wxNOT_FOUND ) {
      m_Scripts.Add( entry );
    }
  }
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetBuildScripts() const {
  return m_Scripts;
}

void CompileOptionsBase::SetCommandsBeforeBuild( const wxArrayString& commands ) {
  if( m_CmdsBefore == commands ) {
    return;
  }
  m_CmdsBefore = commands;
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetCommandsBeforeBuild() const {
  return m_CmdsBefore;
}

void CompileOptionsBase::SetCommandsAfterBuild( const wxArrayString& commands ) {
  if( m_CmdsAfter == commands ) {
    return;
  }
  m_CmdsAfter = commands;
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetCommandsAfterBuild() const {
  return m_CmdsAfter;
}

bool CompileOptionsBase::GetAlwaysRunPostBuildSteps() const {
  return m_AlwaysRunPostCmds;
}

void CompileOptionsBase::SetAlwaysRunPostBuildSteps( bool always ) {
  if( m_AlwaysRunPostCmds == always ) {
    return;
  }
  m_AlwaysRunPostCmds = always;
  SetModified( true );
}

bool CompileOptionsBase::GetModified() const {
  return m_Modified;
}

void CompileOptionsBase::SetModified( bool modified ) {
  m_Modified = modified;
}

void CompileOptionsBase::AddLinkerOption( const wxString& option ) {
  if( m_LinkerOptions.Index( option, s_case_sensitive ) == wxNOT_FOUND ) {
    m_LinkerOptions.Add( option );
    SetModified( true );
  }
}

void CompileOptionsBase::AddLinkLib( const wxString& option ) {
  if( m_LinkLibs.Index( option, s_case_sensitive ) == wxNOT_FOUND ) {
    m_LinkLibs.Add( option );
    SetModified( true );
  }
}

void CompileOptionsBase::SetLinkLibs( const wxArrayString& linkLibs ) {
  if( m_LinkLibs == linkLibs ) {
    return;
  }
  m_LinkLibs = linkLibs;
  SetModified( true );
}

const wxArrayString& CompileOptionsBase::GetLinkLibs() const {
  return m_LinkLibs;
}

void CompileOptionsBase::AddCompilerOption( const wxString& option ) {
  if( m_CompilerOptions.Index( option, s_case_sensitive ) == wxNOT_FOUND ) {
    m_CompilerOptions.Add( option );
    SetModified( true );
  }
}

void CompileOptionsBase::AddResourceCompilerOption( const wxString& option ) {
  if( m_ResourceCompilerOptions.Index( option, s_case_sensitive ) == wxNOT_FOUND ) {
    m_ResourceCompilerOptions.Add( option );
    SetModified( true );
  }
}

void CompileOptionsBase::AddIncludeDir( const wxString& option ) {
  wxString entry = UnixFilename( option );
  if( m_IncludeDirs.Index( entry, s_case_sensitive ) == wxNOT_FOUND ) {
    m_IncludeDirs.Add( entry );
    SetModified( true );
  }
}

void CompileOptionsBase::AddResourceIncludeDir( const wxString& option ) {
  wxString entry = UnixFilename( option );
  if( m_ResIncludeDirs.Index( entry, s_case_sensitive ) == wxNOT_FOUND ) {
    m_ResIncludeDirs.Add( entry );
    SetModified( true );
  }
}

void CompileOptionsBase::AddLibDir( const wxString& option ) {
  wxString entry = UnixFilename( option );
  if( m_LibDirs.Index( entry, s_case_sensitive ) == wxNOT_FOUND ) {
    m_LibDirs.Add( entry );
    SetModified( true );
  }
}

void CompileOptionsBase::AddCommandsBeforeBuild( const wxString& command ) {
  m_CmdsBefore.Add( command );
  SetModified( true );
}

void CompileOptionsBase::AddCommandsAfterBuild( const wxString& command ) {
  m_CmdsAfter.Add( command );
  SetModified( true );
}

void CompileOptionsBase::AddBuildScript( const wxString& script ) {
  wxString envopt = UnixFilename( script );
  if( m_Scripts.Index( envopt, s_case_sensitive ) == wxNOT_FOUND ) {
    m_Scripts.Add( envopt );
    SetModified( true );
  }
}

void CompileOptionsBase::ReplaceLinkerOption( const wxString& option, const wxString& new_option ) {
  int idx = m_LinkerOptions.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_LinkerOptions.Item( idx ) = new_option;
    SetModified( true );
  }
}

void CompileOptionsBase::ReplaceLinkLib( const wxString& option, const wxString& new_option ) {
  int idx = m_LinkLibs.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_LinkLibs.Item( idx ) = new_option;
    SetModified( true );
  }
}

void CompileOptionsBase::ReplaceCompilerOption( const wxString& option, const wxString& new_option ) {
  int idx = m_CompilerOptions.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_CompilerOptions.Item( idx ) = new_option;
    SetModified( true );
  }
}

void CompileOptionsBase::ReplaceResourceCompilerOption( const wxString& option, const wxString& new_option ) {
  int idx = m_ResourceCompilerOptions.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_ResourceCompilerOptions.Item( idx ) = new_option;
    SetModified( true );
  }
}

void CompileOptionsBase::ReplaceIncludeDir( const wxString& option, const wxString& new_option ) {
  int idx = m_IncludeDirs.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_IncludeDirs.Item( idx ) = new_option;
    SetModified( true );
  }
}

void CompileOptionsBase::ReplaceResourceIncludeDir( const wxString& option, const wxString& new_option ) {
  int idx = m_ResIncludeDirs.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_ResIncludeDirs.Item( idx ) = new_option;
    SetModified( true );
  }
}

void CompileOptionsBase::ReplaceLibDir( const wxString& option, const wxString& new_option ) {
  int idx = m_LibDirs.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_LibDirs.Item( idx ) = new_option;
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveLinkerOption( const wxString& option ) {
  int idx = m_LinkerOptions.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_LinkerOptions.RemoveAt( idx );
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveLinkLib( const wxString& option ) {
  int idx = m_LinkLibs.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_LinkLibs.RemoveAt( idx );
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveCompilerOption( const wxString& option ) {
  int idx = m_CompilerOptions.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_CompilerOptions.RemoveAt( idx );
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveResourceCompilerOption( const wxString& option ) {
  int idx = m_ResourceCompilerOptions.Index( option, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_ResourceCompilerOptions.RemoveAt( idx );
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveIncludeDir( const wxString& option ) {
  wxString entry = UnixFilename( option );
  int idx = m_IncludeDirs.Index( entry, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_IncludeDirs.RemoveAt( idx );
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveResourceIncludeDir( const wxString& option ) {
  wxString entry = UnixFilename( option );
  int idx = m_ResIncludeDirs.Index( entry, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_ResIncludeDirs.RemoveAt( idx );
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveLibDir( const wxString& option ) {
  wxString entry = UnixFilename( option );
  int idx = m_LibDirs.Index( entry, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_LibDirs.RemoveAt( idx );
    SetModified( true );
  }
}

void CompileOptionsBase::RemoveCommandsBeforeBuild( const wxString& command ) {
  m_CmdsBefore.Remove( command );
  SetModified( true );
}

void CompileOptionsBase::RemoveCommandsAfterBuild( const wxString& command ) {
  m_CmdsAfter.Remove( command );
  SetModified( true );
}

void CompileOptionsBase::RemoveBuildScript( const wxString& script ) {
  wxString envopt = UnixFilename( script );
  int idx = m_Scripts.Index( envopt, s_case_sensitive );
  if( idx != wxNOT_FOUND ) {
    m_Scripts.RemoveAt( idx );
    SetModified( true );
  }
}

bool CompileOptionsBase::SetVar( const wxString& key, const wxString& value, bool onlyIfExists ) {
  if( onlyIfExists ) {
    StringHash::iterator it = m_Vars.find( key );
    if( it == m_Vars.end() ) {
      return false;
    }
    it->second = value;
    return true;
  }
  m_Vars[key] = value;
  SetModified( true );
  return true;
}

bool CompileOptionsBase::UnsetVar( const wxString& key ) {
  StringHash::iterator it = m_Vars.find( key );
  if( it != m_Vars.end() ) {
    m_Vars.erase( it );
    SetModified( true );
    return true;
  }
  return false;
}

void CompileOptionsBase::UnsetAllVars() {
  m_Vars.clear();
}

bool CompileOptionsBase::HasVar( const wxString& key ) const {
  StringHash::const_iterator it = m_Vars.find( key );
  if( it != m_Vars.end() ) {
    return true;
  }
  return false;
}

const wxString& CompileOptionsBase::GetVar( const wxString& key ) const {
  StringHash::const_iterator it = m_Vars.find( key );
  if( it != m_Vars.end() ) {
    return it->second;
  }
  static wxString emptystring = wxEmptyString;
  return emptystring;
}

const StringHash& CompileOptionsBase::GetAllVars() const {
  return m_Vars;
}
